package com.mhb.generator.engine;

import com.mhb.generator.config.ConstantVal;
import com.mhb.generator.config.GlobalConfig;
import com.mhb.generator.config.StrategyConfig;
import com.mhb.generator.config.ViewConfig;
import com.mhb.generator.config.builder.ConfigBuilder;
import com.mhb.generator.config.po.TableField;
import com.mhb.generator.config.po.TableInfo;
import com.mhb.generator.util.BatchListUtil;
import com.mhb.generator.util.StringUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 模板生成通用抽象
 *
 * @author 博博
 * @Title: TemplateAbstract
 * @time 2019/12/28 0028 17:42
 */
@Log4j2
public abstract class TemplateAbstract {

    private ConfigBuilder configBuilder;

    public TemplateAbstract generate(List<TableInfo> tableInfos) {
        GlobalConfig globalConfig = this.getConfigBuilder().getAutoGenerator().getGlobalConfig();
        ViewConfig viewConfig = this.getConfigBuilder().getAutoGenerator().getViewConfig();
        try {
            for (TableInfo tableInfo : tableInfos) {
                Map<String, Object> generatorMap = getGeneratorMap(tableInfo);
                // entity
                writer(generatorMap, ConstantVal.ENTITY_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.ENTITY_PATH), tableInfo.getEntityName(), ConstantVal.JAVA));
                // mapper
                if (globalConfig.isGenerateMapper()) {
                    writer(generatorMap, ConstantVal.MAPPER_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.MAPPER_PATH), tableInfo.getMapperName(), ConstantVal.JAVA));
                    writer(generatorMap, ConstantVal.XML_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.XML_PATH), tableInfo.getXmlName(), ConstantVal.XML));
                }
                // controller
                if (globalConfig.isGenerateController()) {
                    writer(generatorMap, ConstantVal.CONTROLLER_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.CONTROLLER_PATH), tableInfo.getControllerName(), ConstantVal.JAVA));
                }
                // service
                if (globalConfig.isGenerateService()) {
                    writer(generatorMap, ConstantVal.SERVICE_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.SERVICE_PATH), tableInfo.getServiceName(), ConstantVal.JAVA));
                    writer(generatorMap, ConstantVal.SERVICE_IMPL_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.SERVICE_IMPL_PATH), tableInfo.getServiceImplName(), ConstantVal.JAVA));
                }
                // view
                if (globalConfig.isGenerateTemplate() && viewConfig.isLazyGenerate()) {
                    BatchListUtil<TableField> batchListUtil = new BatchListUtil<>();
                    Map<String, List<TableField>> map = batchListUtil.batchList(tableInfo.getFields(), 2);
                    generatorMap.put("fieldList",map);
                    writer(generatorMap, ConstantVal.TEMPLATE_SELECT_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.TEMPLATE_PATH), tableInfo.getSelectViewName(), viewConfig.getTemplateType().getName()));
                    writer(generatorMap, ConstantVal.TEMPLATE_SAVE_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.TEMPLATE_PATH), tableInfo.getSaveViewName(), viewConfig.getTemplateType().getName()));
                    writer(generatorMap, ConstantVal.TEMPLATE_UPDATE_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.TEMPLATE_PATH), tableInfo.getUpdateViewName(), viewConfig.getTemplateType().getName()));
                    writer(generatorMap, ConstantVal.TEMPLATE_DETAIL_FILE_NAME, configBuilder.getPath(configBuilder.getPathInfo().get(ConstantVal.TEMPLATE_PATH), tableInfo.getDetailViewName(), viewConfig.getTemplateType().getName()));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    public Map<String, Object> getGeneratorMap(TableInfo tableInfo) {
        Map<String, Object> generatorMap = new HashMap<>();
        StrategyConfig strategyConfig = getConfigBuilder().getAutoGenerator().getStrategyConfig();
        GlobalConfig globalConfig = getConfigBuilder().getAutoGenerator().getGlobalConfig();
        ViewConfig viewConfig = getConfigBuilder().getAutoGenerator().getViewConfig();
        generatorMap.put("table", tableInfo);
        generatorMap.put("entitySerialVersionUID", strategyConfig.isEntitySerialVersionUID());
        generatorMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        generatorMap.put("isEntityLomBokModel", strategyConfig.isEntityLomBokModel());
        generatorMap.put("isEntityBuilderModel", strategyConfig.isEntityBuilderModel());
        generatorMap.put("isControllerCRUD", globalConfig.isControllerCRUD());
        generatorMap.put("isPageMethod", globalConfig.isPageMethod());
        generatorMap.put("isGenerateBaseCRUD", globalConfig.isGenerateBaseCRUD());
        generatorMap.put("isGenerateTemplate", globalConfig.isGenerateTemplate());
        generatorMap.put("isGenerateBaseColumnList", globalConfig.isGenerateBaseColumnList());
        generatorMap.put("isGenerateBaseResultMap", globalConfig.isGenerateBaseResultMap());
        generatorMap.put("isMybatisPlus", globalConfig.isMybatisPlus());
        generatorMap.put("author", globalConfig.getAuthor());
        generatorMap.put("templateType", viewConfig.getTemplateType());
        generatorMap.put("pathPrefix", viewConfig.getPathPrefix());
        return generatorMap;
    }

    /**
     * 处理输出目录
     */
    public TemplateAbstract mkdirs() {
        getConfigBuilder().getPathInfo().forEach((key, value) -> {
            File dir = new File(value);
            if (!dir.exists()) {
                boolean result = dir.mkdirs();
                if (result) {
                    log.debug("创建目录： [" + value + "]");
                }
            }
        });
        return this;
    }


    /**
     * 打开输出目录
     */
    public void open() {
        String outDir = getConfigBuilder().getAutoGenerator().getGlobalConfig().getFilePath();
        if (getConfigBuilder().getAutoGenerator().getGlobalConfig().isOpen()
                && StringUtil.isNotNull(outDir)) {
            try {
                String osName = System.getProperty("os.name");
                if (osName != null) {
                    if (osName.contains("Mac")) {
                        Runtime.getRuntime().exec("open " + outDir);
                    } else if (osName.contains("Windows")) {
                        Runtime.getRuntime().exec("cmd /c start " + outDir);
                    } else {
                        log.debug("文件输出目录:" + outDir);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 将模板转化成为文件
     *
     * @param objectMap    渲染对象 MAP 信息
     * @param templatePath 模板文件
     * @param outputFile   文件生成的目录
     */
    public abstract void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception;

    /**
     * 模板真实文件路径
     *
     * @param filePath 文件路径
     */
    public abstract String templateFilePath(String filePath);

    public ConfigBuilder getConfigBuilder() {
        return configBuilder;
    }

    public TemplateAbstract setConfigBuilder(ConfigBuilder configBuilder) {
        this.configBuilder = configBuilder;
        return this;
    }
}
